Skip to content

Comments

tts tts telegram commands with replicate + claude api rate limits + enforce authorized telegram id from env#101

Open
morandalex wants to merge 5 commits intoTinyAGI:mainfrom
morandalex:env-claude-cli-settings-plus-tts-tts-telegram-commands
Open

tts tts telegram commands with replicate + claude api rate limits + enforce authorized telegram id from env#101
morandalex wants to merge 5 commits intoTinyAGI:mainfrom
morandalex:env-claude-cli-settings-plus-tts-tts-telegram-commands

Conversation

@morandalex
Copy link

@morandalex morandalex commented Feb 16, 2026

Summary of Changes

Area Files What changed
Project setup .claudeignore, CLAUDE.md Added Claude Code ignore rules and project documentation
Database layer src/lib/db.ts, db/migrations/*.sql, src/lib/config.ts New SQLite database (better-sqlite3) with WAL mode, token_usage and api_rate_limits tables, dbmate migration support with CREATE TABLE fallback
Token & rate limit tracking src/lib/invoke.ts Pre/post invocation token usage recording, Anthropic rate limit header capture via lightweight API call, tier inference
Speech-to-Text (STT) src/lib/transcribe.ts, src/channels/telegram-client.ts Replicate incredibly-fast-whisper integration, /stton /sttoff toggle commands, voice/audio transcription
Text-to-Speech (TTS) src/lib/synthesize.ts, src/channels/telegram-client.ts Replicate MiniMax Speech-02-Turbo integration, /ttson /ttsoff toggle commands, response voice synthesis
Telegram commands src/channels/telegram-client.ts /help command, user whitelist via TELEGRAM_USERS_ENABLED env var
Agent config src/lib/types.ts, src/lib/invoke.ts env field on AgentConfig, passed to runCommand child process
Visualizer src/visualizer/team-visualizer.tsx Rate limit bars per agent (RPM, input tokens, output tokens), tier badge, rate_limits_updated event handler
Queue processor src/queue-processor.ts dotenv/config import, closeDb() on SIGINT/SIGTERM
Daemon lib/daemon.sh Auto-run dbmate migrations on daemon start
Dependencies package.json, package-lock.json Added better-sqlite3 + @types/better-sqlite3, db:migrate/db:rollback scripts

Pre-requisites

  • Node.js 20+ installed
  • A valid .env file with TELEGRAM_BOT_TOKEN, ANTHROPIC_API_KEY, REPLICATE_API_TOKEN
  • A Telegram account to interact with the bot
  • dbmate fpr the migration

Test Cases

1. Build

  • 1.1 Run npm run build — must compile with zero errors (both main + visualizer)
  • 1.2 Run npm run build:main — must compile with zero errors
  • 1.3 Run npm run build:visualizer — must compile with zero errors
  • 1.4 Verify dist/ output contains channels/telegram-client.js, lib/db.js, lib/transcribe.js, lib/synthesize.js, queue-processor.js

2. Database — with dbmate

  • 2.1 Delete ~/.tinyclaw/tinyclaw.db if it exists
  • 2.2 Run npm run db:migrate — should create the database and apply both migrations
  • 2.3 Verify tables exist: sqlite3 ~/.tinyclaw/tinyclaw.db ".tables" should show token_usage and api_rate_limits
  • 2.4 Run npm run db:rollback twice — should drop both tables cleanly
  • 2.5 Run npm run db:migrate again — idempotent re-apply

3. Database — fallback (no dbmate)

  • 3.1 Temporarily rename/remove dbmate from PATH
  • 3.2 Delete ~/.tinyclaw/tinyclaw.db
  • 3.3 Start the queue processor (npm run queue) — database should be auto-created with both tables via CREATE TABLE IF NOT EXISTS
  • 3.4 Check logs for Database schema created via fallback (dbmate not available)
  • 3.5 Restore dbmate

4. Daemon dbmate auto-migration

  • 4.1 With dbmate installed and a fresh DB, start the daemon via tinyclaw start
  • 4.2 Verify migrations are applied automatically (check logs or verify tables)

5. Telegram — User Whitelist

  • 5.1 Set TELEGRAM_USERS_ENABLED="" (empty) in .env → start bot → all users can send messages (log should show WARN: No TELEGRAM_USERS_ENABLED set)
  • 5.2 Set TELEGRAM_USERS_ENABLED=<your_telegram_id> → restart bot → log should show User whitelist active: 1 user(s) allowed
  • 5.3 Send a message from the whitelisted user → message is queued normally
  • 5.4 Send a message from a non-whitelisted user (or use a different Telegram account) → bot replies Access denied. You are not authorized to use this bot. and log shows WARN: Unauthorized user ... blocked
  • 5.5 Set TELEGRAM_USERS_ENABLED=111,222,333 (multiple IDs with no spaces) → restart → verify 3 user(s) allowed
  • 5.6 Set TELEGRAM_USERS_ENABLED=111, 222, 333 (with spaces) → restart → verify whitespace is trimmed and all 3 IDs work

6. Telegram — /help Command

  • 6.1 Send /help to the bot → should receive the full command list including STT/TTS status
  • 6.2 Send !help to the bot → same result (alternative prefix)
  • 6.3 Verify /help response includes: /agent, /team, /reset, /stton, /sttoff, /ttson, /ttsoff, /help
  • 6.4 Verify STT/TTS status is shown correctly (default: off)

7. Telegram — STT (Speech-to-Text)

  • 7.1 With STT disabled (default), send a voice message → file is downloaded but no transcription (just the audio file is attached to the queue message)
  • 7.2 Send /stton → bot replies Speech-to-text enabled...
  • 7.3 Verify ~/.tinyclaw/stt_enabled_chats.json is created and contains the chat ID
  • 7.4 Send a voice message → log shows Voice transcribed: ... and the queue message contains [voice transcript: ...]
  • 7.5 Send an audio file (.mp3) → same transcription behavior
  • 7.6 Send /sttoff → bot replies Speech-to-text disabled.
  • 7.7 Send another voice message → no transcription
  • 7.8 Restart the Telegram client → STT state is persisted (still off after /sttoff)
  • 7.9 With REPLICATE_API_TOKEN unset or empty, enable STT and send a voice message → transcription silently returns null, no crash

8. Telegram — TTS (Text-to-Speech)

  • 8.1 With TTS disabled (default), send a text message → receive only text response (no voice message)
  • 8.2 Send /ttson → bot replies Text-to-speech enabled...
  • 8.3 Verify ~/.tinyclaw/tts_enabled_chats.json is created and contains the chat ID
  • 8.4 Send a text message and wait for response → receive both a voice message (reply) and the text response
  • 8.5 Verify the voice file is cleaned up after sending (tts_*.mp3 deleted from ~/.tinyclaw/files/)
  • 8.6 Send /ttsoff → bot replies Text-to-speech disabled.
  • 8.7 Next response should be text only (no voice)
  • 8.8 Restart the Telegram client → TTS state is persisted
  • 8.9 With REPLICATE_API_TOKEN unset, enable TTS → response is text-only, log shows TTS failed: ..., no crash

9. Token Usage Tracking

  • 9.1 Send a message through the queue that invokes an agent
  • 9.2 Query sqlite3 ~/.tinyclaw/tinyclaw.db "SELECT * FROM token_usage ORDER BY id DESC LIMIT 1" → row exists with agent_id, provider, model, message_char_count, estimated_input_tokens
  • 9.3 After the agent responds, re-query → same row now has response_char_count, estimated_output_tokens, duration_ms filled in
  • 9.4 Verify estimated_input_tokens ≈ message_char_count / 4 (ceiling)
  • 9.5 Test with an OpenAI/Codex agent → same tracking behavior

10. API Rate Limit Tracking (Anthropic)

  • 10.1 Invoke a Claude (Anthropic) agent
  • 10.2 Query sqlite3 ~/.tinyclaw/tinyclaw.db "SELECT * FROM api_rate_limits ORDER BY id DESC LIMIT 1" → row with rate limit data
  • 10.3 Verify inferred_tier is populated (e.g., Tier 1, Tier 2, etc.)
  • 10.4 Verify log shows Rate limits checked — agent: ..., tier: ..., RPM: ...
  • 10.5 Invoke an OpenAI/Codex agent → no rate limit check should be performed (no new row in api_rate_limits for that agent)
  • 10.6 Configure an agent with custom env (e.g., different API key) → rate limit check is skipped for that agent

11. Agent env Config

  • 11.1 Add "env": { "SOME_VAR": "test" } to an agent in settings.json
  • 11.2 Invoke that agent → the child process should receive SOME_VAR in its environment
  • 11.3 Agent without env field → works as before (inherits parent process env)

12. Visualizer — Rate Limit Display

  • 12.1 Start the visualizer (npm run visualize)
  • 12.2 Before any Claude invocation → rate limits section shows No rate limit data yet
  • 12.3 Trigger a Claude agent invocation → visualizer updates to show rate limit bars for that agent
  • 12.4 Verify the display shows: agent ID, tier badge, model name, RPM bar, Input tokens bar, Output tokens bar, time ago
  • 12.5 Bar colors: green (>50%), yellow (20-50%), red (<20%)
  • 12.6 Multiple agents → each gets their own card in the rate limits row

13. Queue Processor — dotenv & Graceful Shutdown

  • 13.1 Start npm run queue → verify it loads .env (no missing env var errors)
  • 13.2 Send SIGINT (Ctrl+C) → log shows Shutting down queue processor... and database is closed cleanly
  • 13.3 Verify no SQLITE_MISUSE or lock errors in logs after shutdown

14. Existing Functionality (Regression)

  • 14.1 Send a text message to Telegram bot → processed and response received (basic flow still works)
  • 14.2 Send a photo with caption → photo downloaded, caption included in queue message
  • 14.3 Send a document → downloaded correctly
  • 14.4 /agent command still works
  • 14.5 /team command still works
  • 14.6 /reset command still works
  • 14.7 @agent_id routing still works
  • 14.8 @team_id routing still works
  • 14.9 Long messages (>4096 chars) are still split correctly
  • 14.10 Group/channel messages are still ignored (private chat only)

15. Edge Cases

  • 15.1 Database file is locked by another process → graceful error handling, no crash
  • 15.2 REPLICATE_API_TOKEN missing → STT/TTS features degrade silently (return null)
  • 15.3 ANTHROPIC_API_KEY missing → rate limit check skipped, no crash
  • 15.4 Replicate API returns error → TTS/STT return null, logged as error, bot continues
  • 15.5 Very long text (>10k chars) sent to TTS → trimmed to 10k before synthesis
  • 15.6 Multiple rapid messages → token usage rows are unique per invocation
  • 15.7 Bot receives message with no from field → whitelist check handles undefined gracefully

Checklist Before Merge

  • All test cases above pass
  • No console errors or unhandled promise rejections during normal operation
  • .env file is NOT committed (.claudeignore + .gitignore protect it)
  • npm run build succeeds cleanly
  • Database migrations are idempotent
  • Existing Telegram commands (/agent, /team, /reset) still work
  • Bot is stable over 10+ minutes of operation with no memory leaks or crashes

@morandalex
Copy link
Author

reopened from closed pull req #35

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant